"""drawing methods"""
#    Copyright (C) 2011-2012 by
#    Leonardo Bermeo <lbermeoc@unal.edu.co>
#    Joao Carlos Basilio <basilio@poli.ufrj.br>
#    GNU license.

#import  deslab
from deslab.src.automatadefs import fsa
from deslab.src.exceptions import deslabError
from deslab.src.def_const import *
import networkx as nx
import re
from subprocess import call, check_call, check_output, CalledProcessError
import os, sys
import inspect
from working.dot2tex_deslab import convert_graph as latex_code
import warnings

VIEWERS             = {'evince':'evince', 'acrobat reader':'acroread'}
VIEWER              = VIEWERS['evince']
DOTINTERFACE        =  'DotInterfaceFile.dot' 
BEAMERPREAMBLE      =  'BeamerPreamble.tex'
PAGEPREAMBLE        =  'PagePreamble.tex'
FIGUREPREAMBLE      =  'FigurePreamble.tex'
TEXPAGEOUT          =  'TexOutput.tex'
WORKING             =  'working'
OUTPUT              =  'output'
TEXFILES            =  'texfiles'
patternDim =re.compile(r'\\node \(\w\d+\) at \((?P<coordX>\d+\.?\d*)bp,(?P<coordY>\d+\.?\d*)bp\)')
dir_path = {WORKING:'', OUTPUT:'',TEXFILES:''}


# TEMPLATES FOR FIGURES


FIGURE_TEMPLATE=r"""\documentclass{article}
% basic packages
\usepackage{xcolor}
\usepackage[utf8]{inputenc}

\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
% tikz libraries
\usepackage{tikz}
\usetikzlibrary{decorations,arrows,shapes,automata,shadows}
\usetikzlibrary{decorations.markings}
% crop preview environment
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{0pt}%
%colors
\definecolor{plantfill}{rgb}{0.960784,   0.850980,   0.039216}
\definecolor{plantline}{rgb}{0.77647,   0.53725,   0.00000}
\definecolor{superfill}{rgb}{0.54510,   0.88235,   0.15686}
\definecolor{superline}{rgb}{0.227451,   0.486275 ,  0.054902}
\definecolor{specfill}{rgb}{0.42353,   0.43922,   0.72157}
\definecolor{specline}{rgb}{0.00000,   0.05098,   0.36471}
\definecolor{uobsb}{rgb}{0.10980,   0.30196,   0.94510 } 
\definecolor{uobsg}{rgb}{0.035294,   0.533333,   0.458824 } 
\definecolor{auto_color}{rgb}{0,0,0}
\definecolor{bg_color}{rgb}{ 0.98823529,  0.98823529,  0.58039216}

% special arrow definition
\newdimen\dima
\newdimen\dimb

\pgfarrowsdeclare{deslab}{deslab}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \dimb=6\dima\advance\dimb by.5\pgflinewidth%
  \pgfarrowsleftextend{+-\dimb}
  \dimb=2\dima\advance\dimb by0.5\pgflinewidth%
  \pgfarrowsrightextend{+\dimb}
}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \pgfsetdash{}{-0pt}
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{2\dima}{0\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-.5\dima}{.5\dima}}
  {\pgfqpoint{-3\dima}{1.5\dima}}
  {\pgfqpoint{-6\dima}{3.25\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-3\dima}{1\dima}}
  {\pgfqpoint{-3\dima}{-1\dima}}
  {\pgfqpoint{-6\dima}{-3.25\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-3\dima}{-1.5\dima}}
  {\pgfqpoint{-.5\dima}{-.5\dima}}
  {\pgfqpoint{2\dima}{0\dima}}
  \pgfpathclose
  \pgfusepathqfillstroke
}

\pgfarrowsdeclare{deslab'}{deslab'}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \pgfarrowsleftextend{+-4\dima}
  \pgfarrowsrightextend{+6\dima}
}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \pgfpathmoveto{\pgfqpoint{6\dima}{0\dima}}
  \pgfpathcurveto
  {\pgfqpoint{3.5\dima}{.5\dima}}
  {\pgfqpoint{-1\dima}{1.5\dima}}
  {\pgfqpoint{-4\dima}{3.75\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-1.5\dima}{1\dima}}
  {\pgfqpoint{-1.5\dima}{-1\dima}}
  {\pgfqpoint{-4\dima}{-3.75\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-1\dima}{-1.5\dima}}
  {\pgfqpoint{3.5\dima}{-.5\dima}}
  {\pgfqpoint{6\dima}{0\dima}}
  \pgfusepathqfill
}

\pgfarrowsdeclare{init}{init}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \dimb=5.5\dima\advance\dimb by.5\pgflinewidth%
  \pgfarrowsleftextend{+-\dimb}
  \dimb=.5\dima\advance\dimb by0.707\pgflinewidth%
  \pgfarrowsrightextend{+\dimb}
}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}
  \pgfsetmiterjoin
  \pgfpathmoveto{\pgfqpoint{-5.5\dima}{-6\dima}}
  \pgfpathlineto{\pgfqpoint{0.5\dima}{0\dima}}
  \pgfpathlineto{\pgfqpoint{-5.5\dima}{6\dima}}
  \pgfpathclose
  \pgfusepathqfillstroke
}

\pgfarrowsdeclare{init'}{init'}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \pgfarrowsleftextend{+-.5\pgflinewidth}
  \dimb=6\dima\advance\dimb by0.707\pgflinewidth%
  \pgfarrowsrightextend{+\dimb}
}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}
  \pgfsetmiterjoin
  \pgfpathmoveto{\pgfqpoint{0\dima}{-6\dima}}
  \pgfpathlineto{\pgfqpoint{6\dima}{0\dima}}
  \pgfpathlineto{\pgfqpoint{0\dima}{6\dima}}
  \pgfpathclose
  \pgfusepathqstroke
}
% start here
\begin{document}
% setting preview
\pagestyle{empty}
\enlargethispage{100cm}
% font selection
\fontsize{1pt}{1pt}
\selectfont
\tikzset{obs_edge arrow/.style={->, >=deslab, line width =0.075pt}}
\tikzset{accepting/.style={double distance=0.1pt}}

"""

BEAMER_TEMPLATE = r"""\documentclass{beamer}
% basic packages
\usepackage{xcolor}
\usepackage[utf8]{inputenc}

\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
% tikz libraries
\usepackage{tikz}
\usetikzlibrary{decorations,arrows,shapes,automata,shadows}
\usetikzlibrary{decorations.markings}
%colors
\definecolor{plantfill}{rgb}{0.960784,   0.850980,   0.039216}
\definecolor{plantline}{rgb}{0.77647,   0.53725,   0.00000}
\definecolor{superfill}{rgb}{0.54510,   0.88235,   0.15686}
\definecolor{superline}{rgb}{0.227451,   0.486275 ,  0.054902}
\definecolor{specfill}{rgb}{0.42353,   0.43922,   0.72157}
\definecolor{specline}{rgb}{0.00000,   0.05098,   0.36471}
\definecolor{uobsb}{rgb}{0.10980,   0.30196,   0.94510 } 
\definecolor{uobsg}{rgb}{0.035294,   0.533333,   0.458824 } 
\definecolor{auto_color}{rgb}{0,0,0}
\definecolor{bg_color}{rgb}{ 0.98823529,  0.98823529,  0.58039216}
% beamer data
\author{LCA--Lab. de Controle e Automac\~ao}
\title{DESLab Software Package}
\usetheme{Madrid}
\usecolortheme{seagull}
\setbeamercolor{normal text}{bg=bg_color!30}
\usefonttheme{professionalfonts}

% special arrow definition
\newdimen\dima
\newdimen\dimb

\pgfarrowsdeclare{deslab}{deslab}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \dimb=6\dima\advance\dimb by.5\pgflinewidth%
  \pgfarrowsleftextend{+-\dimb}
  \dimb=2\dima\advance\dimb by0.5\pgflinewidth%
  \pgfarrowsrightextend{+\dimb}
}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \pgfsetdash{}{-0pt}
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{2\dima}{0\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-.5\dima}{.5\dima}}
  {\pgfqpoint{-3\dima}{1.5\dima}}
  {\pgfqpoint{-6\dima}{3.25\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-3\dima}{1\dima}}
  {\pgfqpoint{-3\dima}{-1\dima}}
  {\pgfqpoint{-6\dima}{-3.25\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-3\dima}{-1.5\dima}}
  {\pgfqpoint{-.5\dima}{-.5\dima}}
  {\pgfqpoint{2\dima}{0\dima}}
  \pgfpathclose
  \pgfusepathqfillstroke
}

\pgfarrowsdeclare{deslab'}{deslab'}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \pgfarrowsleftextend{+-4\dima}
  \pgfarrowsrightextend{+6\dima}
}
{
  \dima=0.05pt%
  \advance\dima by.3\pgflinewidth%
  \pgfpathmoveto{\pgfqpoint{6\dima}{0\dima}}
  \pgfpathcurveto
  {\pgfqpoint{3.5\dima}{.5\dima}}
  {\pgfqpoint{-1\dima}{1.5\dima}}
  {\pgfqpoint{-4\dima}{3.75\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-1.5\dima}{1\dima}}
  {\pgfqpoint{-1.5\dima}{-1\dima}}
  {\pgfqpoint{-4\dima}{-3.75\dima}}
  \pgfpathcurveto
  {\pgfqpoint{-1\dima}{-1.5\dima}}
  {\pgfqpoint{3.5\dima}{-.5\dima}}
  {\pgfqpoint{6\dima}{0\dima}}
  \pgfusepathqfill
}

\pgfarrowsdeclare{init}{init}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \dimb=5.5\dima\advance\dimb by.5\pgflinewidth%
  \pgfarrowsleftextend{+-\dimb}
  \dimb=.5\dima\advance\dimb by0.707\pgflinewidth%
  \pgfarrowsrightextend{+\dimb}
}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}
  \pgfsetmiterjoin
  \pgfpathmoveto{\pgfqpoint{-5.5\dima}{-6\dima}}
  \pgfpathlineto{\pgfqpoint{0.5\dima}{0\dima}}
  \pgfpathlineto{\pgfqpoint{-5.5\dima}{6\dima}}
  \pgfpathclose
  \pgfusepathqfillstroke
}

\pgfarrowsdeclare{init'}{init'}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \pgfarrowsleftextend{+-.5\pgflinewidth}
  \dimb=6\dima\advance\dimb by0.707\pgflinewidth%
  \pgfarrowsrightextend{+\dimb}
}
{
  \dima=0.05pt%
  \advance\dima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}
  \pgfsetmiterjoin
  \pgfpathmoveto{\pgfqpoint{0\dima}{-6\dima}}
  \pgfpathlineto{\pgfqpoint{6\dima}{0\dima}}
  \pgfpathlineto{\pgfqpoint{0\dima}{6\dima}}
  \pgfpathclose
  \pgfusepathqstroke
}



\begin{document}
%font selection
\fontsize{1pt}{1pt}
\selectfont
\tikzset{obs_edge arrow/.style={->, >=deslab, line width =0.075pt}}
\tikzset{accepting/.style={double distance=0.1pt}}

"""

EMPTY_AUTOMATON = r"""\tikzset{every initial by arrow/.style=
{>=initarrow,initial distance=50pt, draw=specline, line width=4pt, initial where= above, initial text={}}}
\fontsize{30pt}{30pt}
\selectfont
\node (s1) at (2,2) [ellipse,line width=1pt, ball color=superline, path fading=north, fill=superfill!70 ] {
\begin{tabular}{c}
\\
{\textsc{Empty }}
{\textsc{Automaton}}\\
\hline
\\
\textcolor{white}{ Automaton without states}\\
\\
\end{tabular}};

"""

# DESIGN OF STATE RENDERING 

STATE_LAYOUT = {'normal': {'state':'inner sep= 0.25pt, minimum size=0pt, circle,','init_pos':''},
                'rectangle': {'state': 'minimum height=0pt, inner sep=0.3pt, inner xsep=0.1pt, rectangle', 'init_pos': ''}, 
                'crectangle': {'state': 'minimum height=0mm, inner sep=2mm, chamfered rectangle', 'init_pos': ''}, 
                'verifier': {'state': 'minimum height=0pt, inner sep=0.3pt, inner xsep=0.1pt, rectangle', 'init_pos': 'above'},  
                'diagnoser': {'state': 'minimum height=0pt, inner xsep=0.1pt, inner ysep=0.3pt, rectangle', 'init_pos': 'above'}, 
                'observer': {'state': 'minimum height=0pt, inner sep=0.3pt, inner xsep=0.1pt, rectangle', 'init_pos': 'above'}, 
                'vertical': {'state': 'inner sep=0.2pt, minimum size=0pt, circle', 'init_pos': 'above'}}   


COLOR_TEMPLATE = ''
PREAMBLE_DIC = {'beamer': BEAMER_TEMPLATE,
                'figure': FIGURE_TEMPLATE,
                'figurecolor': FIGURE_TEMPLATE}


global fig_counter, window_counter 
fig_counter = 1
window_counter = 0




def create_digraph(self) :
    """ This function creates a digraph containing a map
     between an alias for each state, and event, in order
     to draw a right graph with standarized label size  """
     
    def tex(symbol):
        """ This function converts the symbol used in textual
        interface to the latex label that will be renderized
        """
        if self.symDict == {}:
            converted = symbol        
        elif symbol in self.symDict:
            converted = self.symDict[symbol]
        elif symbol in self.X | self.Sigma:
            converted = symbol 
        else: 
            raise  invalidLabel, 'Symbol %s was not recognized'%(symbol)
        return converted  
           
    Graph       = self.Graph    
    nxDigraph   = nx.MultiDiGraph()
    Siguobs     = self.Sigma-self.Sigobs
    Sigobs      = self.Sigobs
    Sigcon      = self.Sigcon  
    Siguncon    = self.Sigma-self.Sigcon 
    
    if os.name == 'nt':
        styleNodeDic ={'initial': '"state,initial"',
                       'marked': '"state,accepting"',
                       'initialmarked': '"state,initial,accepting"',
                       'normal':'"state"'} 
    else: 
        styleNodeDic ={'initial': "state,initial",
                       'marked': "state,accepting",
                       'initialmarked': "state,initial,accepting",
                       'normal': "state"}       
        
    for node in Graph.nodes_iter(data=True): 
        symbol = node[0]       
        if symbol in (self.Xm & self.X0) :
            actualStyle=styleNodeDic['initialmarked']
        elif symbol in self.Xm :
            actualStyle=styleNodeDic['marked']
        elif symbol in self.X0: 
            actualStyle=styleNodeDic['initial']            
        else:
            actualStyle=styleNodeDic['normal']                                      
        nxDigraph.add_node(node[1]['label'], label = tex(symbol), style=actualStyle)
    
        
    for source in Graph.nodes_iter():               
        for target in Graph.successors_iter(source):
            events       = Graph.get_edge_data(source,target).keys()
            events_obs   = [tex(i)+',' for i in sorted(list(set(events) & Sigobs))]                  
            events_unobs = [tex(i)+',' for i in sorted(list(set(events) & Siguobs))]              
            events_obs   = ''.join(events_obs).rstrip(',')         
            events_unobs = ''.join(events_unobs).rstrip(',')                  
            source_dig   = Graph.node[source]['label']
            target_dig   = Graph.node[target]['label']
            
            if  events_obs <> '':                       
                if  os.name == 'nt':   # in the case if windows system               
                    events_obs = r'"'+events_obs+r'"'
                nxDigraph.add_edge(source_dig, target_dig, key=events_obs,
                                   label=events_obs, style='obs_edge arrow') # we have to fix the labels problem
            if  events_unobs <> '':               
                if  os.name == 'nt':             
                    events_unobs = r'"'+events_unobs+r'"'  
                nxDigraph.add_edge(source_dig, target_dig, key=events_unobs,
                                   label=events_unobs, style='unobs_edge arrow')
    
   
    return nxDigraph


def setupdir():    
    """This function recover the absolute path of the user and 
    set the basic directories for drawing"""
    path_drawing       = inspect.currentframe().f_code.co_filename
    graphics_path      = os.path.dirname(path_drawing)    
    dir_path[WORKING]  = os.path.join(graphics_path, WORKING)
    dir_path[OUTPUT]   = os.path.join(graphics_path, OUTPUT)
    dir_path[TEXFILES] = os.path.join(graphics_path, TEXFILES)    
    return

def auto2dot(automaton):    
    """ 
    This function creates a dot description
    of the input automaton
    """
    digraph_aut = create_digraph(automaton)
    name_dotfile = os.path.join(dir_path[WORKING], DOTINTERFACE)     
    nx.write_dot(digraph_aut, name_dotfile)
    file_obj  = open(name_dotfile)
    dot_string = file_obj.read()
    dot_string = dot_string.replace('strict','')
    dot_string = dot_string.lstrip()
    file_obj.close()
    return dot_string


def determine_size(texfile, nodes):
    """This function parses the created text file in order 
    to get the ratio for rendering the graphics in Beamer mode"""
    if nodes == 0:
        size='50mm'
        return size
    coordX=[]
    coordY=[]
    
    for match in patternDim.finditer(texfile):
        coordX.append(float(match.group('coordX')))
        coordY.append(float(match.group('coordY')))
    FigureWidth = max(coordX) - min(coordX)
    FigureHeight = max(coordY) - min(coordY)
    
    miliWidth, miliHeight =  FigureWidth*25.4/72.0, FigureHeight*25.4/72.0 
    
    if (miliWidth == 0) & (miliHeight <> 0):
        factorSize = 20/miliHeight
        newSize = miliHeight*factorSize
        size = str(newSize)+'mm'    
  
    elif (miliWidth <> 0) & (miliHeight == 0):
        size = '100mm' 
    elif (miliWidth == 0) & (miliHeight == 0):
        size = '20mm'
    else:        
        aspectRelation = miliWidth/miliHeight
        if aspectRelation >= 1.57:            
            size = '100mm'
        else:           
           factorSize = 60/miliHeight
           newSize = miliWidth*factorSize
           size = str(newSize)+'mm'    
    return size




def automaton2tikfig(auto, nodesep=0.2,ranksep=0.2, direction='LR', program ='dot'):
        
               
    #environment variables
    dot_init = auto2dot(auto)  
    graph = auto.Graph
    preamble = 'rankdir=%s;\nnodesep=%s;\nranksep=%s;\n'%(direction, str(nodesep), str(ranksep))
    for x_i in auto.X0 :
        preamble += '\t'+graph.node[x_i]['label']+' '+'[style="state"];\n'
    for x_m in auto.Xm :
        preamble += '\t'+graph.node[x_m]['label']+' '+'[style="state,accepting"];\n'     
    auto_dotfile = dot_init[0:11] + preamble + dot_init[11:]# texcommands
    file = os.path.join(dir_path[WORKING], DOTINTERFACE)      
    fileObj = open(file, 'w')
    fileObj.write(auto_dotfile)
    fileObj.close()
    command = '%s -Txdot %s | '%(program, DOTINTERFACE) + 'python dot2tex_deslab.py -ftikz --codeonly --texmode math'
    try:
        fig_texcode = check_output(command,shell=True, cwd = dir_path[WORKING], stderr=0)  
    except CalledProcessError:
        raise deslabError,  'I could not create a tex file of the automaton object'
    return fig_texcode

    
def tex2pdf(Texfilename) :    
    global window_counter
    window_counter += 1    
    pdf_outputname = 'Figure-'+str(window_counter)+str(fig_counter)
    command = 'pdflatex'+' '+'-interaction=batchmode'+ ' ' + '-no-shell-escape'
    command = command +' ' +'-output-directory'+' '+dir_path[OUTPUT]+' '+'-jobname'+' '+ pdf_outputname +' '+Texfilename
    try:
        retcode = check_call(command,shell=True, cwd = dir_path[WORKING])  
    except CalledProcessError:
        raise deslabError, "There is a trouble with the generation of the pdf file. Check pdflatex installation"
    return pdf_outputname+'.pdf'
     
    
   
def automaton2page(automaton, style, size='0.9\hsize', nodesep=0.25,ranksep=0.25, direction='LR',
                   program='dot', LineColor=['blue',80], FillColor=['blue',20]):     
       
    strLineColor=LineColor[0]+'!'+str(LineColor[1])
    strFillColor=FillColor[0]+'!'+str(FillColor[1])
                    
    if automaton.style in STATE_LAYOUT:
        aut_sty = STATE_LAYOUT[automaton.style]['state'] 
        init_pos = STATE_LAYOUT[automaton.style]['init_pos'] 
    else:
        aut_sty = STATE_LAYOUT['normal']['state']
        init_pos = STATE_LAYOUT['normal']['init_pos'] 
      
    if automaton == fsa():
        tikz_code = EMPTY_AUTOMATON          
    else:
        tikz_code = automaton2tikfig(automaton, nodesep, ranksep, direction, program)+'\n'  
    
    nodes=len(automaton.X)       
    size = determine_size(tikz_code, nodes)   
              
    if style == 'beamer':    
        init_tex = r"""        
\tikzset{unobs_edge arrow/.style={>=deslab, dash pattern=on 0.1pt off 0.15pt, draw = %s,
line width =0.075pt, decoration={markings,mark=at position 1 with {\arrow[fill= %s]{>}}},
postaction={decorate}
}}

\tikzset{every initial by arrow/.style=
{>=init, initial distance=1.7pt,line width=0.125pt, initial where=%s, fill =%s, draw =%s, initial text={}}}

\tikzset{every state/.style={draw= %s, fill= %s, line width = 0.1, %s}}
        
\begin{frame}       
\frametitle{\textcolor{auto_color}{\textcolor{white}{\framebox{Fig. \; %s.%s }\quad} %s}}
\begin{center}
\resizebox{%s}{!}{
\begin{tikzpicture}
""" % ('uobsg', 'uobsg', init_pos, 'yellow!60', 'green!30!black',
         strLineColor, strFillColor, aut_sty, str(window_counter),
         str(fig_counter), automaton.name, size)
       
        figure_texcode = init_tex + tikz_code +'\\end{tikzpicture}} \n \\end{center} \n \\end{frame}'
        
        
    elif style == 'figurecolor':
        init_tex = r"""        
\tikzset{unobs_edge arrow/.style={>=deslab, dash pattern=on 0.1pt off 0.15pt, draw = %s,
line width =0.075pt, decoration={markings,mark=at position 1 with {\arrow[fill= %s]{>}}},
postaction={decorate}
}}

\tikzset{every initial by arrow/.style=
{>=init, initial distance=1.7pt,line width=0.1pt, initial where=%s, fill =%s, draw =%s, initial text={}}}

\tikzset{every state/.style={draw= %s, fill= %s, line width = 0.1, %s}}

\begin{tikzpicture}
""" % ('uobsg', 'uobsg', init_pos, 'orange!40', 'red!60!black',
         strLineColor, strFillColor, aut_sty)
        figure_texcode = init_tex + tikz_code + '\\end{tikzpicture}\n\\newpage\n'
        
        
    elif style == 'figure':
        init_tex = r"""        
\tikzset{unobs_edge arrow/.style={>=deslab, dash pattern=on 0.1pt off 0.15pt, draw = %s,
line width =0.075pt, decoration={markings,mark=at position 1 with {\arrow[fill= %s]{>}}},
postaction={decorate}
}}

\tikzset{every initial by arrow/.style=
{>=deslab, initial distance=1.7pt,line width=0.075pt, initial where=%s, fill =%s, draw =%s, initial text={}}}

\tikzset{every state/.style={draw= %s, fill= %s, line width = 0.1, %s}}

\begin{tikzpicture}
""" % ('black', 'black', init_pos, 'black', 'black',
         'black', 'white', aut_sty)
        figure_texcode = init_tex + tikz_code + '\\end{tikzpicture}\n\\newpage\n'
                
    else :
        raise deslabError, 'style %s is not defined yet'%style    
    return figure_texcode 


def write_texfile(TexString,TexfileOut):
    TexComplete = TexString+r'\end{document}'
    Texpresfile = os.path.join(dir_path[WORKING], TexfileOut)      
    fileObj = open(Texpresfile, 'w')
    fileObj.write(TexComplete)
    fileObj.close()
    return TexfileOut



def openviewer(filepdf):         
    # absolute path of the output of th pdf
    filepath = os.path.join(dir_path[OUTPUT], filepdf)         
    if sys.platform.startswith('darwin'): # mac system
        call((VIEWER, filepath))
    elif os.name == 'nt': # Windows system
        os.startfile(filepath)        
    elif os.name == 'posix': # Linux    
        command = VIEWER+' '+filepath+'&'
    try:
        retcode = check_call(command,shell=True,stderr=0)
    except CalledProcessError:
        raise deslabError, 'Fail opening the pdf viewer'
    return  
        



      
def draw(*automatavars):      
    global fig_counter 
    setupdir() # we setup the directories in the current operative system 
    
    # the last argument is an fsa then we use the default style
    if isinstance(automatavars[-1], fsa):          
        AutomataList=list(automatavars[0:-1])
        AutomataList.append(automatavars[-1])
        style='beamer'
    # the last argument  is a list then we have a vector of automata
    # we must setup the default style
    elif isinstance(automatavars[-1],list):   
        AutomataList=automatavars[-1] 
        style='beamer'
    # the last argument  is a style
    # and we have a list of automata   
    elif isinstance(automatavars[-1],str) & isinstance(automatavars[-2],list) :
        AutomataList = automatavars[-2]
        style = automatavars[-1]  
    # we have a comma separated automata and one defined style
    else :
        style=automatavars[-1] 
        AutomataList=list(automatavars[0:-1])
    # we setup the preamble
    if style in PREAMBLE_DIC:
        preamble_tex = PREAMBLE_DIC[style]
    else:
        preamble_tex = PREAMBLE_DIC['figure']        
   
    fig_counter = 1 
    # we generate the latex code for every automata passed to draw function 
    for automaton in AutomataList: 
        #in the case of a large automata we avoid rendering
        if len(automaton.X)>100:
            print "Current version of DESlab supports drawings up to 100 states"
            continue
        if automaton.empty == False:
            AutLineColor, AutFillColor, prog, nsep, rsep, direct_rend = automaton.LineColor, automaton.FillColor,  automaton.render, automaton.nodesep, automaton.ranksep ,automaton.direction
            preamble_tex += automaton2page(automaton,style,
                                                  LineColor=AutLineColor,FillColor=AutFillColor,program=prog,nodesep=nsep,ranksep=rsep, direction=direct_rend)      
        else:
            preamble_tex += automaton2page(automaton, style)
        fig_counter += 1
    write_texfile(preamble_tex,TEXPAGEOUT)
    page_pdf = tex2pdf(TEXPAGEOUT)    
    openviewer(page_pdf)
    return 




""" These are basic functions for plotting networkx graphs instead of
 the ugly matplotlib, it is only experimental work """
 
 
 
 
def graph2tikfig(graph, nodesep,ranksep, direction, LineColor, FillColor):           
    scale = '1'
    initpos=''
    shape = 'circle'
    DrawFileDot = graph2dot(graph)
    strLineColor=LineColor[0]+'!'+str(LineColor[1])
    strFillColor=FillColor[0]+'!'+str(FillColor[1])
    preamble=[]
    preamble.append('\trankdir='+direction+';\n')
    preamble.append('\tnodesep='+str(nodesep)+';\n')
    preamble.append('\tranksep='+str(ranksep)+';\n') 
    preamble.append('\tsize=4,4'+';\n') 
    preamble.append('\tfontsize=1'+';\n') 
    Preamble=reduce(lambda x, y: x+y, preamble)
    AutoDot=DrawFileDot[0:11]+Preamble+DrawFileDot[11:]# texcommands
    file = os.path.join(dir_path[WORKING], DOTINTERFACE)      
    fileObj = open(file, 'w')
    fileObj.write(AutoDot)
    fileObj.close()
    #comm1 = 'python dot2tex.py --preproc --texmode math  %s | '%DOTINTERFACE 
    comm1 = 'dot -Txdot %s | '%DOTINTERFACE  
    comm2 = 'python dot2tex.py -ftikz --codeonly --texmode math'
    #comm2 = 'python dot2tex.py -ftikz --codeonly '
 
    command =comm1+comm2
    texonly = check_output(command,shell=True, cwd = dir_path[WORKING])
    figureTexcode = []  
    figureTexcode.append(r"""\begin{tikzpicture}[scale="""+
                         scale+""",>=stealth',line join=bevel,line width=0.75pt,"""+'\n')
    
    figureTexcode.append(initpos+',initial text=,every state/.style={'+
                         shape+',draw='+strLineColor+
                        ','+'very thick'+',fill='+strFillColor+'},]'+'\n')
    figureTexcode.append(texonly)
    figureTexcode.append('\end{tikzpicture}\n')
    figureTexcode.append(r'\newpage'+'\n')
    figureTexcode=reduce(lambda x, y: x+y, figureTexcode)    
    return figureTexcode
 

def graph2dot(graph):    
    """ 
    This function creates a dot description
    of the input automaton
    """
    NameDotfile = os.path.join(dir_path[WORKING], DOTINTERFACE)     
    nx.write_dot(graph,NameDotfile)
    fileObj     = open(NameDotfile)
    DrawFileDot = fileObj.read()
    DrawFileDot = DrawFileDot.replace('strict','')
    DrawFileDot = DrawFileDot.lstrip()
    fileObj.close()
    return DrawFileDot


def label_digraph(graph,type): 
    
    def latex_D (xd):   
        xd_tex = []
        for x,l in xd:
            xd_tex.append(str(x)+l)            
        xd_tex = reduce(lambda i,j: i+ ','+j, (t for t in xd_tex))
        xd_tex = r'\{' + xd_tex + r'\}'                  
        return xd_tex
    
    
    def latex(n):
        if type == 'lex':
            return str(n)
        elif type== 'lex-label':
            if n[0]==():
                name = '(\\epsilon,'+n[1]+')'
            else:
                name = '('+reduce(lambda x,y: x+y, (i for i in n[0]))+','+n[1]+')'
            return name
        
        elif type== 'lex-cycle':
            if graph.in_degree(n)==0:
                return '('+str(n[0])+','+'\\epsilon'+')'            
            
            if len(n)==2:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+ str(n[0])+','+ pref +')'
                         

            elif len(n)==3:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                if pref == epsilon:                    
                    pref = pref.replace(epsilon,'\\epsilon ')
                else:
                    pref = pref.replace(epsilon,'')
                    
                name = '('+ str(n[0]) + ',' + pref + ',' +reduce(lambda x,y: x+y, (i for i in n[2])) +')'                
            return name
        
        elif type == 'FPES' or type == 'XDS':
            if graph.in_degree(n)==0:
                return '('+ latex_D(n[0])+','+'\\epsilon'+')'            
            
            if len(n)==2:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+  latex_D(n[0])+','+ pref +')'
                         

            elif len(n)==3:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+ latex_D(n[0]) + ',' + pref + ',' +reduce(lambda x,y: x+y, (i for i in n[2])) +')'                
            return name
        
        
        elif type == 'lex-Gd-G':
            if graph.in_degree(n)==0:
                return '('+ latex_D(n[0][0])+','+ str(n[0][1]) +','+'\\epsilon'+')'            
            
            if len(n)==2:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+  latex_D(n[0][0])+','+ str(n[0][1]) +','+ pref +')'
                         

            elif len(n)==3:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+ latex_D(n[0][0])+','+ str(n[0][1]) + ',' + pref + ',' +reduce(lambda x,y: x+y, (i for i in n[2])) +')'                
            return name
        
        elif type == 'XST':
            if graph.in_degree(n)==0:
                return '('+ latex_D(n[0][0])+','+ latex_D(n[0][1]) +','+'\\epsilon'+')'            
            
            if len(n)==2:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+  latex_D(n[0][0])+','+ latex_D(n[0][1]) +','+ pref +')'
                         

            elif len(n)==3:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+ latex_D(n[0][0])+','+ latex_D(n[0][1]) + ',' + pref + ',' +reduce(lambda x,y: x+y, (i for i in n[2])) +')'      
                
            elif len(n)==4:
                pref =  reduce(lambda x,y: x+y, (i for i in n[1]))
                pref = pref.replace(epsilon,'')
                name = '('+ latex_D(n[0][0])+','+ latex_D(n[0][1]) + ',' + pref +',' +reduce(lambda x,y: x+y, (i for i in n[2])) +','+ str(n[3]) +')'          
            return name
        
        
        
        
        
    
    s = iter(range(len(graph)))   
    ren = dict([(n, 's'+str(next(s))) for n in graph])
    graph_label = nx.DiGraph()
    
    
    
    for n in graph.nodes_iter():
        if graph.out_degree(n)==0:
            style_n = 'ellipse, fill = plantfill!50'
        elif n==():
            style_n = 'circle'
        else:
            style_n = 'rectangle'        
          
        graph_label.add_node(ren[n], label= latex(n), style=style_n)   
    for n1, n2 in graph.edges_iter():
        graph_label.add_edge(ren[n1], ren[n2])             
    return graph_label
        
        
        

def drawgraph(graph, type='lex',nodesep=0.25,ranksep=0.2, direction='LR',
                LineColor=['blue',60],FillColor=['blue',15]):
    global fig_counter 
    setupdir() 
    fig_counter=1
    graph_label = label_digraph(graph,type) 
    tex_code = graph2tikfig(graph_label, nodesep,ranksep, direction , LineColor, FillColor)
    tex_code = texpreamble('figure') + tex_code
    write_texfile(tex_code,TEXPAGEOUT)
    page_pdf = tex2pdf(TEXPAGEOUT)      
    openviewer(page_pdf)
    return
    
    
     
        
        
        
        
        
    
    


